﻿using log4net;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace HuChaHuRen.HeNan.XiangCheng.Common
{
    public class HttpOp
    {
        private static ILog logger = LogManager.GetLogger("HttpOp");

        public static string Post(string url, 
            string body,
            Dictionary<string, string> headers = null,
            string contentType = null)
        {

            Encoding encoding = Encoding.UTF8;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.Accept = "*/*";
            if (headers != null && headers.Count > 0)
            {
                var webHeaders = new WebHeaderCollection();
                foreach (var kvp in headers)
                {
                    webHeaders.Add(kvp.Key, kvp.Value);
                }

                //content-type 默认为 application/json;charset=UTF-8
                //if (!headers.ContainsKey("Content-Type"))
                //{
                //    webHeaders.Add("Content-Type", "application/json;charset=UTF-8");
                //}

                request.Headers = webHeaders;
            }

            if(!string.IsNullOrEmpty(contentType))
            {
                request.ContentType = contentType;
            }
            else
            {
                request.ContentType = "application/json;charset=UTF-8";
            }

            request.Timeout = 3000;
            byte[] buffer = encoding.GetBytes(body);
            HttpWebResponse response = null;
            request.ContentLength = buffer.Length;
            try
            {
                request.GetRequestStream().Write(buffer, 0, buffer.Length);
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (Exception ex)
            {
                logger.Error($"接口‘{url}’调用异常:\n{ex.Message}");
            }
            if (response != null)
            {
                using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
                {
                    return reader.ReadToEnd();
                }
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// HttpWebRequest发送文件
        /// </summary>
        /// <param name="url">url</param>
        /// <param name="fileBytes">文件流</param>
        /// <param name="fileName">文件名</param>
        /// <param name="contentType">contentType</param>
        /// <param name="nameValueCollection">其余要附带的参数键值对</param>
        public static string UploadFile(string url,
            byte[] fileBytes, 
            string fileName,
            string contentType, 
            NameValueCollection nameValueCollection)
        {
            string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
            byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.ContentType = "multipart/form-data; boundary=" + boundary;
            request.Method = "POST";
            request.KeepAlive = true;
            request.Credentials = CredentialCache.DefaultCredentials;
            Stream requestStream = request.GetRequestStream();
            //string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
            foreach (string key in nameValueCollection.Keys)
            {
                requestStream.Write(boundarybytes, 0, boundarybytes.Length);
                string formitem = $"Content-Disposition: form-data; name=\"{key}\"\r\n\r\n{nameValueCollection[key]}"; 
                //string.Format(formdataTemplate, key, nameValueCollection[key]);
                byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
                requestStream.Write(formitembytes, 0, formitembytes.Length);
            }
            requestStream.Write(boundarybytes, 0, boundarybytes.Length);
            //$"Content-Disposition: form-data; name=\"{paramName}\"; filename=\"{fileName}\"\r\nContent-Type: {contentType}\r\n\r\n";
            string header = $"Content-Disposition: form-data; filename=\"{fileName}\"\r\nContent-Type: {contentType}\r\n\r\n";
            byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
            requestStream.Write(headerbytes, 0, headerbytes.Length);
            //FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            //byte[] buffer = new byte[4096];
            //int bytesRead = 0;
            //while ((bytesRead = fileBytes.Read(buffer, 0, buffer.Length)) != 0)
            //{
                requestStream.Write(fileBytes, 0, fileBytes.Length);
            //}
            //fileBytes.Close();
            byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
            requestStream.Write(trailer, 0, trailer.Length);
            requestStream.Close();
            WebResponse webResponse = null;
            string respContent = string.Empty;
            try
            {
                webResponse = request.GetResponse();
                Stream responseStream = webResponse.GetResponseStream();
                StreamReader streamReader = new StreamReader(responseStream);
                respContent = streamReader.ReadToEnd();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                request = null;
            }
            return respContent;
        }

        /// <summary>
        /// 使用multipart/form-data方式上传文件及其他数据
        /// </summary>
        /// <param name="url">接口地址</param>
        /// <param name="headers">请求头参数</param>
        /// <param name="nameValueCollection">键值对参数</param>
        /// <param name="fileCollection">文件参数：参数名，文件路径</param>
        /// <returns>接口返回结果</returns>
        public static string PostMultipartFormData(string url,
            Dictionary<string, string> headers,
            NameValueCollection nameValueCollection, 
            string fileName,
            byte[] fileByte)
        {
            using (var client = new HttpClient())
            {
                // 头名称误用。请确保将请求头用于 HttpRequestMessage，将响应头用于 HttpResponseMessage，将内容头用于 HttpContent 对象。
                // client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "multipart/form-data;charset=utf-8");
                
                foreach (var item in headers)
                {
                    client.DefaultRequestHeaders.TryAddWithoutValidation(item.Key, item.Value);
                }

                using (var content = new MultipartFormDataContent())
                {
                    // 键值对参数
                    string[] allKeys = nameValueCollection.AllKeys;
                    foreach (string key in allKeys)
                    {
                        var dataContent = new ByteArrayContent(Encoding.UTF8.GetBytes(nameValueCollection[key]));
                        dataContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                        {
                            Name = key
                        };
                        content.Add(dataContent);
                    }

                    //处理文件内容
                    //原版 入参是： NameValueCollection fileCollection
                    //string[] fileKeys = fileCollection.AllKeys;
                    //foreach (string key in fileKeys)
                    //{
                    //    byte[] bmpBytes = File.ReadAllBytes(fileCollection[key]);
                    //    var fileContent = new ByteArrayContent(bmpBytes);//填充文件字节
                    //    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                    //    {
                    //        Name = key,
                    //        FileName = Path.GetFileName(fileCollection[key])
                    //    };
                    //    content.Add(fileContent);
                    //}

                    // Name, 用了硬编码，懒得参数化了
                    var fileContent = new ByteArrayContent(fileByte);
                    //填充文件字节
                    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                    {
                        Name = "examPdf",
                        FileName = fileName
                    };
                    content.Add(fileContent);

                    var result = client.PostAsync(url, content).Result;
                    //post请求
                    string data = result.Content.ReadAsStringAsync().Result;
                    return data;//返回操作结果
                }
            }
        }

    }
}
